/*
 * @Description: 用户权限
 * @Author: DHL
 * @Date: 2021-12-22 21:52:44
 * @LastEditors: DHL
 * @LastEditTime: 2023-12-29 11:48:06
 */

import { defineStore } from 'pinia'
import { store } from '@/store'
import { AppRouteModule, IMenu } from '@/types/router'
import { dynamicImport } from '@/router/helper/routeHelper'
import { BasicRoute, LayoutRoute, DynamicRoute } from '@/router/dynamicRoute'
import { useLoginUserStore } from './loginUser'
import { addRouter } from '@/router'
import { isNotEmpty } from '@/utils/isUtils'

interface IPermissionState {
  /**
   * 许可代码列表
   * 资源主键
   * 用于控制页面细粒度控制
   */
  permCodeList: string[]

  /**
   * 菜单列表
   */
  menuList: object[]

  /**
   * 菜单树
   */
  menuTree: IMenu[]

  /**
   * 异步路由
   */
  asyncRouter: AppRouteModule[]

  /**
   * 动态路由是否已添加
   */
  isDynamicAddedRoute: boolean
}

const permissionStore = defineStore({
  id: 'permissionStore',
  state: (): IPermissionState => ({
    permCodeList: [],
    menuList: [],
    menuTree: [],
    asyncRouter: [],
    isDynamicAddedRoute: false
  }),
  getters: {
    getPermCodeList(): string[] {
      return this.permCodeList
    },

    getMenuTree(): IMenu[] {
      return this.menuTree
    }
  },
  actions: {
    /**
     * 初始化权限
     */
    buildPermission(resources: Nullable<object[]>) {
      if (resources && resources.length > 0) {
        this.setMenuList(resources)
        this.setPermCodeList(resources)
      }

      this.setRoutes()
    },

    /**
     * 设置许可代码列表
     * 用于控制页面细粒度控制
     * @param resources
     */
    setPermCodeList(resources: object[]) {
      let ids: string[] = []
      resources.forEach((res: any) => {
        // 资源类型（0-菜单；1-功能；2-页签）
        if (res.resType === '1' && !ids.includes(res.id)) {
          ids.push(res.id)
        }
      })
      this.permCodeList = ids
    },

    /**
     * 资源集合
     * @param resources
     */
    setMenuList(resources: object[]) {
      let menus: object[] = []
      resources.forEach((res: any) => {
        // 资源类型（0-菜单；1-功能；2-页签）
        if (res.resType === '0') {
          this.formatResIdToPath(res)
          menus.push(res)
        }
      })
      this.menuList = menus
      this.setMenuTree()
    },

    /**
     * 左侧菜单
     */
    setMenuTree() {
      this.menuTree = this.menuListToTree('')
    },

    /**
     * 设置异步路由
     * @returns
     */
    setRoutes() {
      return new Promise<void>((resolve) => {
        const loginUserStore = useLoginUserStore()
        loginUserStore.initLoginUserByLocalStorage()

        let routerList: AppRouteModule[] = []
        let basicRouteList: AppRouteModule[] = []

        for (const menu of this.menuList) {
          const { id, path, name, url, iscache, target, openType } = menu as any
          if (url) {
            const isCache = '1' === iscache ? true : false
            let component: any = null

            // 主窗口打开模式（1-单页模式；2-ifream模式）
            if ('2' === openType) {
              component = dynamicImport('/iframe/index')
            } else {
              component = dynamicImport(url)
            }

            const router: AppRouteModule = {
              path: path,
              name: id,
              component: component,
              meta: {
                title: name,
                isCache: isCache,
                target: target,
                openType: openType
              }
            }
            routerList.push(router)

            // 主窗口打开模式（1-单页模式；2-ifream模式）
            if ('2' === openType) {
              const ifreamComponent = dynamicImport(url)
              const ifreamRouter: AppRouteModule = {
                path: `${path}/ifream`,
                name: `${id}Iframe`,
                component: ifreamComponent,
                meta: {
                  title: name
                }
              }
              basicRouteList.push(ifreamRouter)
            }
          }
        }

        LayoutRoute.children = [...DynamicRoute, ...routerList] as any
        BasicRoute.children = [...basicRouteList] as any

        this.asyncRouter.push(LayoutRoute)
        this.asyncRouter.push(BasicRoute)

        resolve()
      })
    },

    /**
     * 设置路由
     */
    buildRoutesAction() {
      if (this.asyncRouter.length > 0) {
        // 动态添加路由
        addRouter(this.asyncRouter)

        this.isDynamicAddedRoute = true
      }
    },

    /**
     * 清理
     */
    clearPermission() {
      this.permCodeList = []
      this.menuList = []
      this.menuTree = []
      this.asyncRouter = []
      this.isDynamicAddedRoute = false
    },

    /**
     * 菜单 list 转 tree
     */
    menuListToTree(pidVal: string) {
      // 资源菜单集合
      let menuTree: IMenu[] = []
      const itemMap = {}

      for (const menu of this.menuList) {
        const { id, path, name, iconCls, parentResId } = menu as any

        let menuItem: IMenu = {
          id: id,
          path: path,
          name: name,
          icon: iconCls
        }

        const pid = parentResId || ''

        if (!itemMap[id]) {
          itemMap[id] = {
            children: []
          }
        }

        itemMap[id] = {
          ...menuItem,
          children: itemMap[id]['children']
        }

        const treeItem = itemMap[id]

        if (pid === pidVal) {
          menuTree.push(treeItem)
        } else {
          if (!itemMap[pid]) {
            itemMap[pid] = {
              children: []
            }
          }
          itemMap[pid].children.push(treeItem)
        }
      }

      return menuTree
    },

    /**
     * 格式化资源ID为路由path值
     * @param res
     */
    formatResIdToPath(res: { id: string; path: string }) {
      let id = res.id

      id = id.toLowerCase()

      let path = id.replace(/\_(\w)/g, function (all: any, letter: any) {
        return letter.toUpperCase()
      })

      path = path.replace(/\-(\w)/g, function (all: any, letter: any) {
        return letter.toUpperCase()
      })

      path = path.replace('twb', '').replace('tw', '')

      res.path = path
    },

    resetState(): void {
      this.permCodeList = []
      this.menuTree = []
    }
  }
})

export function usePermissionStore() {
  return permissionStore(store)
}
